home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crack It!
/
Crack It!.iso
/
CONTENT
/
DISKEDIT
/
DISKEDIT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-09-13
|
36KB
|
1,223 lines
{
***
DISKEDIT
Disk View/Edit Utility Version 3.00
(C)Copyright Gerard Paul Java 1996
Program Source File
This program allows viewing and editing of individual logical disk sectors.
It deals with logical DOS drives, rather than the physical drives in the
computer.
This allows unrestricted access and modification to any DOS disk's sector.
Therefore, extreme caution must be exercised when modifying any sector,
especially if it is the system area (boot, FAT, root directory).
This program is intended only for IBM PCs, XTs, ATs, PS/2s, and their 100%
compatible computers, running on DOS version 2.10 or later. No provisions
for porting over to other computers, operating systems, or Pascal compilers
exist. The program will most likely not run on systems other than those
mentioned above.
Do not use this program on any multitasking operating environment such
as Windows. The disk access is absolute, and the operating system
may be disrupted by this. This program will either not function properly
or may cause corrupted data. Use only under single-tasking DOS mode
if necessary.
This program is free software; you may distribute and/or modify it under
the terms of the GNU General Public License version 2 or (at your option)
any later version, as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but is
provided "AS IS", WITHOUT ANY WARRANTY, either expressed or implied,
including, but not limited to, warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
675 Mass Ave., Cambridge, MA 02139 USA.
REVISION HISTORY:
Version 3.00 - 5/23/94 Blue/white color scheme
***
}
{$A+,B-,F-,I-,R-,S-,V-}
{$M 3072,0,10752}
program DiskEdit;
uses
Dos,
Crt,
ScreenRt,
AbsDisk,
HexFuncs,
SysRt,
Instruc,
Error,
IntroRt,
MenuRt;
const
Selected = True;
NotSelected = False;
ErrInst1 = 'Press R to retry or Esc to cancel';
RetryOrCancel = 'R'+Esc;
type
Parameter1Type = string[2];
HexByte = string[2];
KeysString = string[3];
ParaType = array[0..15] of byte;
DataListType = ^ParaRecord;
ParaRecord = record
Paragraph: ParaType;
Next,Prev: DataListType;
end;
PtrRecord = record
Offset: word;
Segment: word;
end;
DiskObjType = object
List: DataListType;
SectorSize: word;
NumSectors: longint;
Drive: byte;
LargePartition: boolean;
BtoA: boolean;
procedure SetDrive(var Signal: boolean);
procedure Operate;
end;
var
Parameter1: Parameter1Type;
Regs: Registers;
BackScreenBuff: ScreenBufferType;
MenuScreenBuff: ScreenBufferType;
AuxScreenBuffer: ScreenBufferType;
SectorList: DiskObjType;
Menu: MenuType;
{---------------------------------------------------------------------------
InitValues: Sets the color attributes depending on the screen mode and the
BW environment variable.
---------------------------------------------------------------------------}
procedure InitValues;
begin
if (LastMode = Mono) or (GetEnv('BW') = '1') then
begin
NormOptKeyAttr := $7F;
SelectedOptKeyAttr := $F;
OptionNormTextAttr := $70;
OptionSelectedTextAttr := $7;
BoxAttr := $7F;
TextNormAttr := $70;
HelpLineTextAttr := $F;
ErrBoxAttr := $F;
ErrMsgAttr := $F;
TextHighAttr := $7F;
end
else
begin
TextNormAttr := $1E;
BoxAttr := $13;
TextHighAttr := $1B;
NormOptKeyAttr := $1B;
SelectedOptKeyAttr := $B;
OptionNormTextAttr := $1E;
OptionSelectedTextAttr := $E;
HelpLineTextAttr := $71;
ErrBoxAttr := $4F;
ErrMsgAttr := $4E;
end;
SetTSSRValues;
end;
{---------------------------------------------------------------------------
ShowHelpScreen: The DISKEDIT help system.
---------------------------------------------------------------------------}
procedure ShowHelpScreen(ScreenNo: byte);
begin { proc }
Window(1,1,80,25);
SaveScreen(AuxScreenBuffer); { Save screen. }
JustSeeBox;
TextAttr := BoxAttr;
case ScreenNo of
0: begin
DrawBox(3,3,78,23,DoubleLine);
GotoXY(31,3);Write(' Help: Help System ');
Window(5,5,78,25);TextAttr := TextNormAttr;
Writeln('At almost any point in this program, press F1 for help (help is not');
Writeln('available at error and instruction boxes). Each help screen contains');
Writeln('instructions on what to do at the point from where it was invoked.');
Writeln;
Writeln('The bottom line of the sector view/edit screen contains a list of the');
Writeln('function keys available, and their corresponding functions. The help');
Writeln('screen contains more detailed instructions.');
Writeln;
Writeln('This program can modify any disk sector. So BE VERY CAREFUL WHEN');
Writeln('CHANGING THE DISK DATA! CORRUPTED DATA IN ANY OF THE RESERVED SECTORS');
Writeln('(boot sector, FATs, root directory) COULD MAKE PART OR ALL OF THE DISK');
Writeln('INACCESSIBLE, AND IMPROPER MODIFICATION OF THE DATA AREA CAN CORRUPT');
Writeln('DATA IN THE FILES.');
Writeln;
Writeln('See the manual for details.');
Writeln;
end; { 0 }
1: begin
DrawBox(3,6,78,19,DoubleLine);
GotoXY(30,6);Write(' Help: Menu Operation ');
Window(5,8,78,20);TextAttr := TextNormAttr;
Writeln('The Up and Down cursor keys move the selection bar up and down respect-');
Writeln('ively. Home and End move it to the first and last options respectively.');
Writeln('Enter executes the option indicated by the bar.');
Writeln;
Writeln('Pressing the highlighted letters directly executes their corresponding');
Writeln('options.');
Writeln;
Writeln('The bottom line of the screen shows a description of the function of the');
Writeln('option indicated by the selection bar.');
end; { 1 }
2: begin
GotoXY(24,25);ClrEol;
DrawBox(3,3,78,23,DoubleLine);
GotoXY(29,3);Write(' Help: View/Edit Screen');
Window(5,5,78,24);TextAttr := TextNormAttr;
Writeln('Use the cursor keys to move the cursor around the data dump. Use the');
Writeln('PgUp and PgDn keys to read the previous and next sectors respectively.');
Writeln('Use Home and End to read the first and last disk sectors respectively.');
Writeln('Press F5 to view a specific sector.');
Writeln;
Writeln('To edit a sector, use the F2 key to select the edit mode (hex or ASCII)');
Writeln('and enter the new data. Enter hexadecimal numbers in hex mode, type in');
Writeln('the new data in ASCII mode. (In hex mode, the Backspace key moves the');
Writeln('cursor back one character if the first digit has already been changed.');
Writeln('In ASCII mode, it enters an ASCII 8 character.) Press F4 to write the');
Writeln('changes to disk, or F3 to discard them.');
Writeln;
Writeln('The edit mode is indicated by the location of the blinking cursor. In');
Writeln('hex mode, it is positioned on the hex dump. In ASCII mode, it is on the');
Writeln('ASCII dump.');
Writeln;
end;
end;
Writeln;
TextAttr := TextHighAttr;Write(ContMsg); { Display message. }
WaitForKeypress;
RestoreScreen(AuxScreenBuffer); { Get rid of help. }
end; { proc }
{---------------------------------------------------------------------------
CommandHelp: Displays information on the DISKEDIT command.
---------------------------------------------------------------------------}
procedure CommandHelp;
begin
Writeln;
Writeln('Help on the DISKEDIT command:');
Writeln;
Writeln('Command syntax: DISKEDIT [/?]');
Writeln;
Writeln('The command takes no parameters other than /?, which brings up this screen.');
Writeln('Set the CGASNOWCHECK environment variable to 1 (with a SET CGASNOWCHECK=1');
Writeln('command from the DOS prompt) to suppress "snow" on old CGAs. Likewise set');
Writeln('BW environment variable to 1 to bring the program up in black-and-white mode.');
Writeln;
Writeln;
Writeln('DISKEDIT Version 3.00: (C)Copyright Gerard Paul Java 1996');
end;
{---------------------------------------------------------------------------
IndicateError: Displays an error box and waits for the response.
---------------------------------------------------------------------------}
procedure IndicateError(Msg1,Msg2: ErrStrType;ValidKeys: KeysString;
var Keystroke: char);
begin
SaveScreen(AuxScreenBuffer);
Window(1,25,80,25);TextAttr := TextNormAttr;
ClrEol;
ErrBox(Msg1,Msg2,Instruct);
repeat
Keystroke := Upcase(GetKeyNoExt);
until Pos(Keystroke,ValidKeys) <> 0;
RestoreScreen(AuxScreenBuffer);
end;
procedure MemError;
type
MemValStr = string[4];
var
ShortMem: MemValStr;
begin
SaveScreen(AuxScreenBuffer);
Str(10240-MemAvail,ShortMem);
ErrBox('Error: not enough memory (short by '+ShortMem+' bytes)',
'Press a key to return to menu',Instruct);
WaitForKeypress;
RestoreScreen(AuxScreenBuffer);
end;
{---------------------------------------------------------------------------
SetDrive: Sets the drive whose disk will be accessed, and the proper
parameters the program will use to properly access the disk.
---------------------------------------------------------------------------}
procedure DiskObjType.SetDrive(var Signal: boolean);
type
DriveStr = string[1];
var
BootPtr: pointer;
EnteredDrive: DriveStr;
Keystroke: char;
Result: word;
OldDrive: byte;
ReservedSectors: word;
DumFile: file;
IOCode: longint;
begin
TextAttr := BoxAttr;
Window(1,1,80,25);
DrawBox(32,11,49,13,DoubleLine);
TextAttr := TextNormAttr;
GotoXY(2,25);Write('Enter a drive letter');ClrEol;
GotoXY(34,12);Write('Enter drive: ');
TextAttr := $F;
Write(' ');
GotoXY(47,12);GetInput(EnteredDrive,1,Signal);
RestoreScreen(BackScreenBuff);
{ Equate drive B to A on single-floppy systems }
if ((BIOSEquipList and $00C0) = 0) and (EnteredDrive = 'B') then
begin
EnteredDrive := 'A';
BtoA := True;
end
else
BtoA := False;
if not Signal then
begin
if EnteredDrive <> '' then
begin
Assign(DumFile,EnteredDrive+':\NUL'); { Check if drive valid. }
Reset(DumFile); { Error if drive not found. }
end;
IOCode := IOResult;
if (IOCode = 3) or (EnteredDrive = '') then
begin
SaveScreen(AuxScreenBuffer);
ErrBox('Error: invalid drive entered','Press a key to return to menu',Instruct);
WaitForKeypress;
RestoreScreen(AuxScreenBuffer);
Signal := True;
end
else
begin
if IOCode = 0 then
Close(DumFile); { Release handle. }
repeat
Drive := Ord(EnteredDrive[1])-65; { Get num value of drive. }
Regs.AH := $19; { Save current drive. }
Intr($21,Regs);
OldDrive := Regs.AL;
{ Set current drive for }
Regs.AH := $E; { function $1F. }
Regs.DL := Drive;
Intr($21,Regs);
Regs.AH := $1F; { Undocumented Get Disk Info function. }
Intr($21,Regs);
if Regs.AL <> 0 then
begin
IndicateError('Error reading disk',ErrInst1,
RetryOrCancel,Keystroke);
if Keystroke = Esc then
Signal := True
else
Window(1,1,80,25);
end;
until (Regs.AL = 0) or (Signal);
if not Signal then
begin
SectorSize := MemW[Regs.DS:Regs.BX+2];
if MaxAvail < SectorSize+((SectorSize div 16)*SizeOf(ParaRecord)) then
begin
MemError;
Signal := True;
end
else
begin
ReservedSectors := MemW[Regs.DS:Regs.BX+$B];
NumSectors := ReservedSectors+
((MemW[Regs.DS:Regs.BX+$D]-1)*
(longint(Mem[Regs.DS:Regs.BX+4]+1)));
GetMem(BootPtr,SectorSize);
AbsRead(Drive,0,1,BootPtr,Result);
FreeMem(BootPtr,SectorSize);
LargePartition := (Result = $FFFF);
end;
end;
Regs.AH := $E; { Restore current drive. }
Regs.DL := OldDrive;
Intr($21,Regs);
end;
end;
end;
{---------------------------------------------------------------------------
AdvancePointer: Advances a pointer value by one byte. Keeps the segment
and offset values normalized (offset is always 0..15).
---------------------------------------------------------------------------}
procedure AdvancePointer(var PtrVar: pointer);
begin
if PtrRecord(PtrVar).Offset = $0F then
begin
PtrRecord(PtrVar).Offset := 0;
Inc(PtrRecord(PtrVar).Segment);
end
else
Inc(PtrRecord(PtrVar).Offset);
end;
{---------------------------------------------------------------------------
Operate: The procedure which allows scrolling of sectors, reading
sectors, editing sectors, and writing sectors.
---------------------------------------------------------------------------}
procedure DiskObjType.Operate;
type
SectorNumStrType = string[10];
const
ASCMinOffset = 59;
ASCMaxOffset = 74;
DiscardWarning = 'Warning: changes have not been saved';
DiscardInstruc = 'Press D to discard or Esc to resume editing';
CancelKey = 'C';
DiscardKey = 'D';
DiscardOrReturn = DiscardKey+Esc;
var
ListPtr: DataListType;
xPos,yPos: byte;
ParaOffset: word;
Keystroke: char;
CurChar: byte;
ASCIIEdit: boolean;
xHexPos: byte;
PosInHex: byte;
ParaIdx: byte;
HeapMark: pointer;
CurSector: longint;
OldSector: longint;
MaxSector: longint;
SectorBuffer: pointer;
DataChanged: boolean;
RespKey: char;
TerminateLoop: boolean;
SectorNumStr: SectorNumStrType;
Signal: boolean;
StrError: integer;
{---------------------------------------------------------------------------
ListInSector: Copies the contents of the sector buffer into a linked list
of paragraphs.
---------------------------------------------------------------------------}
procedure ListInSector;
var
Ctr: word;
ParaIndex: byte;
ListPtr: DataListType;
tNode: DataListType;
BufPtr: pointer;
NumIncs: word;
begin
BufPtr := SectorBuffer;
NumIncs := SectorSize div 16;
for Ctr := 1 to NumIncs do
begin
New(tNode);
if List = nil then
begin
List := tNode;
tNode^.Prev := nil;
end
else
begin
tNode^.Prev := ListPtr;
ListPtr^.Next := tNode;
end;
ListPtr := tNode;
for ParaIndex := 0 to 15 do
begin
ListPtr^.Paragraph[ParaIndex] := Byte(BufPtr^);
AdvancePointer(BufPtr);
end;
end;
ListPtr^.Next := nil;
end;
{---------------------------------------------------------------------------
ShowOneLine: Displays the offset, the hex values of the paragraph, and the
ASCII representation of the paragraph.
---------------------------------------------------------------------------}
procedure ShowOneLine(ParaPtr: DataListType;Offset: word);
var
Ctr: byte;
AccString: string[52];
begin
AccString := ' ';
for Ctr := 0 to 15 do
AccString := AccString+' '+ToHex(ParaPtr^.Paragraph[Ctr]);
GotoXY(1,WhereY);Write(ToHex(Hi(Offset)),
ToHex(Lo(Offset)),AccString);
for Ctr := 0 to 15 do
PutChar(ASCMinOffset+Ctr,WhereY,ParaPtr^.Paragraph[Ctr]);
end;
{---------------------------------------------------------------------------
Show16Lines: Displays the first paragraphs of the sector.
---------------------------------------------------------------------------}
procedure Show16Lines;
var
Ctr: byte;
ListPtr: DataListType;
LastLineNum: byte;
begin
ListPtr := List;
LastLineNum := SectorSize div 16;
if LastLineNum > 16 then
LastLineNum := 16;
for Ctr := 0 to LastLineNum-1 do
begin
GotoXY(1,Ctr+1);ShowOneLine(ListPtr,Ctr*16);
ListPtr := ListPtr^.Next;
end;
end;
{---------------------------------------------------------------------------
Cursor. . .: Move the cursor on the specified direction. Include
provisions for wrapping and scrolling.
---------------------------------------------------------------------------}
procedure CursorUp;
begin
PosInHex := 1;
if ListPtr^.Prev <> nil then
begin
Dec(ParaOffset,16);
if yPos <> 1 then
Dec(yPos)
else
begin
InsLine;
ShowOneLine(ListPtr^.Prev,ParaOffset);
end;
end;
if ListPtr^.Prev <> nil then
ListPtr := ListPtr^.Prev;
end;
procedure CursorDown;
begin
PosInHex := 1;
if ListPtr^.Next <> nil then
begin
Inc(ParaOffset,16);
if (yPos <> 16) then
Inc(yPos)
else
if ListPtr^.Next <> nil then
begin
GotoXY(1,1);DelLine;
GotoXY(1,16);ShowOneLine(ListPtr^.Next,ParaOffset);
end;
end;
if ListPtr^.Next <> nil then
ListPtr := ListPtr^.Next;
end;
procedure CursorLeft;
begin
PosInHex := 1;
if xPos > ASCMinOffset then
Dec(xPos)
else
begin
xPos := ASCMaxOffset;
CursorUp;
end;
end;
procedure CursorRight;
begin
PosInHex := 1;
if xPos < ASCMaxOffset then
Inc(xPos)
else
begin
xPos := ASCMinOffset;
CursorDown;
end;
end;
{---------------------------------------------------------------------------
IndicateChar: Displays the specified character at the current location in
the current attribute.
---------------------------------------------------------------------------}
procedure IndicateChar(Ch: byte);
begin
SetCursor($FFFF);
GotoXY(xPos,yPos);PutChar(xPos,yPos,Ch);
GotoXY(xHexPos,yPos);Write(ToHex(Ch));
end;
{---------------------------------------------------------------------------
IndicateChange: Indicates on the screen whether any bytes have been
changed.
---------------------------------------------------------------------------}
procedure IndicateChange;
begin
Window(61,23,80,23);
TextAttr := BoxAttr;
if DataChanged then
Write(' Changes unsaved ')
else
Write(StringOf(#205,17));
Window(4,5,78,20);
end;
{---------------------------------------------------------------------------
DumpSector: Copies the sector data to the list, and displays the first
16 paragraphs.
---------------------------------------------------------------------------}
procedure DumpSector;
begin
Release(HeapMark);
List := nil;
ListInSector;
TextAttr := TextNormAttr;Window(4,5,78,20);
Show16Lines;
ParaOffset := 0;
xPos := ASCMinOffset;yPos := 1;
ListPtr := List;
end;
{---------------------------------------------------------------------------
ReadInSector: Reads in the sector into a buffer, and accepts sets up the
list, and shows the first 16 paragraphs on the screen.
---------------------------------------------------------------------------}
procedure ReadInSector(var Keystroke: char);
var
Result: word;
Signal: boolean;
WarningKey: char;
ErrorCode: boolean;
begin
if DataChanged then
begin
IndicateError(DiscardWarning,
DiscardInstruc,
DiscardOrReturn,WarningKey);
Window(4,5,78,20);
if WarningKey = DiscardKey then
begin
DataChanged := False;
IndicateChange;
Signal := True;
end
else
begin
Signal := False;
Keystroke := CancelKey;
end;
end
else
Signal := True;
if Signal then
begin
repeat
if LargePartition then
AugAbsRead(Drive,CurSector,1,SectorBuffer,Result)
else
AbsRead(Drive,CurSector,1,SectorBuffer,Result);
Signal := ((Result and $100) <> 0);
if Signal then
begin
IndicateError('Error reading disk sector',
'Press R to retry, C to cancel, or Esc to end edit',
'RC'+Esc,Keystroke);
if Keystroke = CancelKey then
Window(4,5,78,20);
end;
until (not Signal) or (Keystroke = Esc) or (Keystroke = CancelKey);
if (not Signal) then
begin
TextAttr := TextHighAttr;
Window(33,22,80,22);
Write(CurSector:10);
DumpSector;
Keystroke := #0;
end;
end;
end;
{---------------------------------------------------------------------------
WriteSector: Writes the current sector to disk.
---------------------------------------------------------------------------}
procedure WriteSector;
var
ListPtr: DataListType;
BufPtr: pointer;
Ctr: byte;
Result: word;
Keystroke: char;
ErrMsg: ErrStrType;
IsError: boolean;
begin
if DataChanged then
begin
ListPtr := List;
BufPtr := SectorBuffer;
while ListPtr <> nil do
begin
for Ctr := 0 to 15 do
begin
byte(BufPtr^) := ListPtr^.Paragraph[Ctr];
AdvancePointer(BufPtr);
end;
ListPtr := ListPtr^.Next;
end;
IsError := False;
repeat
if LargePartition then
AugAbsWrite(Drive,CurSector,1,SectorBuffer,Result)
else
AbsWrite(Drive,CurSector,1,SectorBuffer,Result);
if ((Result and $100) <> 0) then
begin
IsError := True;
if Lo(Result) = 0 then
ErrMsg := 'Error: disk is write-protected'
else
ErrMsg := 'Error writing disk sector';
IndicateError(ErrMsg,ErrInst1,RetryOrCancel,Keystroke);
Window(4,5,78,20);
end
else
begin
IsError := False;
DataChanged := False;
IndicateChange;
end;
until (not IsError) or (Keystroke = Esc);
end;
end;
begin
List := nil;
TextAttr := TextHighAttr;
GotoXY(11,25);Write('F2');
GotoXY(32,25);Write('F3');
GotoXY(44,25);Write('F4');
GotoXY(55,25);Write('F5');
TextAttr := TextNormAttr;
GotoXY(13,25);Write('-change edit mode');
GotoXY(34,25);Write('-discard');
GotoXY(46,25);Write('-update');
GotoXY(57,25);Write('-new sector');
GetMem(SectorBuffer,SectorSize);
Mark(HeapMark);
ASCIIEdit := False;
PosInHex := 1;
MaxSector := NumSectors-1;
CurSector := 0;
TextAttr := BoxAttr;
DrawBox(2,3,79,23,DoubleLine);
GotoXY(3,3);Write(' Offset ');
GotoXY(13,3);Write(' Hex Dump ');
GotoXY(62,3);Write(' ASCII Dump ');
TextAttr := TextNormAttr;
GotoXY(4,22);Write('Drive:');
GotoXY(25,22);Write('Sector: ');
TextAttr := TextHighAttr;
GotoXY(11,22);
if BtoA then
Write('B')
else
Write(Chr(Drive+65));
DataChanged := False;
repeat
ReadInSector(RespKey);
if RespKey = CancelKey then
Inc(CurSector);
until (RespKey = #0) or (RespKey = Esc);
if RespKey <> Esc then
begin
TerminateLoop := False;
repeat
ParaIdx := xPos-ASCMinOffset;
CurChar := ListPtr^.Paragraph[ParaIdx];
xHexPos := (xPos-ASCMinOffset-1)*3+11;
TextAttr := $0F;
IndicateChar(CurChar);
SetCursor($000F);
if ASCIIEdit then
GotoXY(xPos,yPos)
else
GotoXY(xHexPos+PosInHex-1,yPos);
Keystroke := ReadKey;
TextAttr := TextNormAttr;
IndicateChar(CurChar);
case Keystroke of
#0: case ReadKey of
F1: begin
ShowHelpScreen(2);
Window(4,5,78,20);
end;
UpKey: CursorUp;
DownKey: CursorDown;
LeftKey: if (not ASCIIEdit) and (PosInHex = 2) then
PosInHex := 1
else
CursorLeft;
RightKey: CursorRight;
#60: ASCIIEdit := not ASCIIEdit;
#61: begin
if DataChanged then
begin
DumpSector;
DataChanged := False;
IndicateChange;
end;
end;
EndKey: begin
OldSector := CurSector;
CurSector := MaxSector;
ReadInSector(RespKey);
if RespKey = CancelKey then
CurSector := OldSector
else if RespKey = Esc then
TerminateLoop := True;
end;
HomeKey: begin
OldSector := CurSector;
CurSector := 0;
ReadInSector(RespKey);
if RespKey = CancelKey then
CurSector := OldSector
else if RespKey = Esc then
TerminateLoop := True;
end;
PgUpKey: begin
if CurSector <> 0 then
begin
Dec(CurSector);
ReadInSector(RespKey);
if RespKey = CancelKey then
Inc(CurSector)
else if RespKey = Esc then
TerminateLoop := True;
end;
end;
PgDnKey: begin
if CurSector <> MaxSector then
begin
Inc(CurSector);
ReadInSector(RespKey);
if RespKey = CancelKey then
Dec(CurSector)
else if RespKey = Esc then
TerminateLoop := True;
end;
end;
#62: WriteSector;
#63: begin
SaveScreen(AuxScreenBuffer);
Window(1,1,80,25);
TextAttr := TextNormAttr;
GotoXY(2,25);ClrEol;
Write('Enter a sector number');
TextAttr := BoxAttr;
DrawBox(23,12,57,14,DoubleLine);
TextAttr := TextNormAttr;
GotoXY(25,13);Write('Enter sector number: ');
TextAttr := $F;
GetInput(SectorNumStr,10,Signal);
RestoreScreen(AuxScreenBuffer);
if not Signal then
begin
OldSector := CurSector;
Val(SectorNumStr,CurSector,StrError);
if (CurSector > MaxSector) or (CurSector < 0) or
(StrError <> 0) then
begin
SaveScreen(AuxScreenBuffer);
ErrBox('Error: invalid sector number entered',
ContMsg,Instruct);
WaitForKeypress;
RestoreScreen(AuxScreenBuffer);
Window(4,5,78,20);
CurSector := OldSector;
end
else
begin
ReadInSector(RespKey);
if RespKey = CancelKey then
CurSector := OldSector
else if RespKey = Esc then
TerminateLoop := True;
end;
end
else
Window(4,5,78,20);
end;
end;
Esc: if DataChanged then
begin
IndicateError(DiscardWarning,
DiscardInstruc,
DiscardOrReturn,RespKey);
if RespKey = DiscardKey then
TerminateLoop := True
else
Window(4,5,78,20);
end
else
TerminateLoop := True;
else
begin
if ASCIIEdit then
begin
ListPtr^.Paragraph[ParaIdx] := Ord(Keystroke);
IndicateChar(Ord(Keystroke));
CursorRight;
if not DataChanged then
begin
DataChanged := True;
IndicateChange;
end;
end
else
begin
Keystroke := UpCase(Keystroke);
case Keystroke of
'0'..'9',
'A'..'F': begin
if PosInHex = 1 then
begin
PosInHex := 2;
ListPtr^.Paragraph[ParaIdx] := (ListPtr^.Paragraph[ParaIdx] and $0F)+
FromHex(Keystroke)*16;
end
else
begin
ListPtr^.Paragraph[ParaIdx] := (ListPtr^.Paragraph[ParaIdx] and $F0)+
FromHex(Keystroke);
IndicateChar(ListPtr^.Paragraph[ParaIdx]);
CursorRight;
end;
if not DataChanged then
begin
DataChanged := True;
IndicateChange;
end;
end;
#8: PosInHex := 1;
end;
end;
end;
end;
MemW[$40:$1A] := MemW[$40:$1C]; { Clear keyboard buffer }
until TerminateLoop;
end;
RestoreScreen(BackScreenBuff);
end;
{---------------------------------------------------------------------------
ProgInterface: the program interface procedure, sets up the screen and
calls the menu procedure.
---------------------------------------------------------------------------}
procedure ProgInterface;
var
BarPos: byte;
TerminateLoop: boolean;
Signal: boolean;
{--------------------------------------------------------------------------
IntroScreen: Draws the introductory box. This box disappears when a key
other than F1 is pressed. F1 brings up a screen showing information on
the built-in help system.
--------------------------------------------------------------------------}
procedure IntroScreen;
var
Keystroke : char;
TerminateLoop : boolean;
Postn : byte;
begin
DrawDesktop;
GotoXY(2,1);TextAttr := TextNormAttr;Write('DISKEDIT Version 3.00');
SaveScreen(BackScreenBuff);
DrawIntroBox;
TextAttr := TextNormAttr;
Writeln('DISKEDIT');
Writeln('Disk View/Edit Utility Version 3.00');
Writeln('(C)Copyright Gerard Paul Java 1996');
Writeln;
TextAttr := TextHighAttr;
Write('Press F1 for help on help, any other key to continue');
TerminateLoop := FALSE;
repeat
Keystroke := UpCase(ReadKey);
case Keystroke of
ExtKey: if ReadKey = F1 then
begin
ShowHelpScreen(0);
end
else
TerminateLoop := TRUE;
else
TerminateLoop := TRUE;
end;
until TerminateLoop;
Window(1,1,80,25);
RestoreScreen(BackScreenBuff);
GotoXY(2,25);Write('F1');
TextAttr := TextNormAttr;Write('-help');
SaveScreen(BackScreenBuff);
end;
begin
IntroScreen;
Menu.Init;
with Menu do
begin
AddItem('^View/edit disk sectors','Allows viewing and editing of sectors');
AddItem('E^xit program','Exits program');
end;
Menu.SetScreenPos(25,10);
Menu.Show;
SaveScreen(MenuScreenBuff);
BarPos := 1;
TerminateLoop := False;
repeat
Menu.Operate(BarPos,Signal);
if Signal then
ShowHelpScreen(1)
else
if BarPos = 1 then
begin
RestoreScreen(BackScreenBuff);
SectorList.SetDrive(Signal);
if not Signal then
SectorList.Operate;
RestoreScreen(MenuScreenBuff);
end
else
TerminateLoop := True;
until TerminateLoop;
end;
begin
Parameter1 := ParamStr(1);
if Parameter1 = '/?' then
CommandHelp
else
begin
CheckBreak := BreakOff;
ScreenInit;
if GetEnv('CGASNOWCHECK') = '1' then
CheckSnow := SnowCheckOn
else
CheckSnow := SnowCheckOff;
InitValues;
ProgInterface;
Release(HeapOrg);
TerminateProg(0);
end;
end.